package com.tensquare.notice.netty;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.tensquare.notice.config.ApplicationContextProvider;
import entity.Result;
import entity.StatusCode;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;

import java.util.HashMap;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author wz
 * @company 公司
 * @create 2020-02-25 14:30
 */
public class MyWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    private static ObjectMapper mapper = new ObjectMapper();

    //从spring容器中获取消息监听容器,处理订阅消息sysNoticeContainer
    SimpleMessageListenerContainer sysNoticeContainer = (SimpleMessageListenerContainer) ApplicationContextProvider.getApplicationContext()
            .getBean("sysNoticeContainer");

    //从spring容器中获取点赞监听容器,处理点赞消息userNoticeContainer
    SimpleMessageListenerContainer userNoticeContainer = (SimpleMessageListenerContainer) ApplicationContextProvider.getApplicationContext()
            .getBean("userNoticeContainer");

    //存放webSocket连接Map,根据用户id存放
    public static ConcurrentHashMap<String, Channel> userChannelMap = new ConcurrentHashMap<>();

    //从Spirng容器中获取RabbitTemplate
    RabbitTemplate rabbitTemplate = ApplicationContextProvider.getApplicationContext()
            .getBean(RabbitTemplate.class);

    //用户请求webSocket服务端,执行方法
    //第一次请求,建立websocket连接
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        //约定用户第一次请求携带的数据 : {"userId":"1"}
        //获取用户请求数据解析
        String json = msg.text();
        //解析json数据,获取用户id
        String userId = mapper.readTree(json).get("userId").asText();
        //第一次请求,建立websocket连接
        Channel channel = userChannelMap.get("userId");
        if (channel == null) {
            //获取webSocket连接
            channel = ctx.channel();
            //把连接放到容器中
            userChannelMap.put(userId, channel);
        }
        //只完成新消息的提醒即可,只需要获取消息的数量
        //获取rabbitMQ消息内容,发送给用户
        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate);
        //拼接获取队列名称
        String queueName = "article_subscribe_" + userId;
        //获取rabbit的properties容器  rabbitAdmin中的源码获取数量
        Properties queueProperties = rabbitAdmin.getQueueProperties(queueName);
        //消息总数量
        int noticeCount = 0;
        //判断properties是否不为空
        if (queueProperties != null) {
            //如果不为空,获取消息数量
            noticeCount = (int) queueProperties.get("QUEUE_MESSAGE_COUNT");
        }


        //=====================================

        //拼接获取队列名称
        String userQueueName = "article_thumbup_" + userId;
        //获取rabbit的properties容器  rabbitAdmin中的源码获取数量
        Properties userQueueProperties = rabbitAdmin.getQueueProperties(queueName);
        //消息总数量
        int userNoticeCount = 0;
        //判断properties是否不为空
        if (userQueueProperties != null) {
            //如果不为空,获取消息数量
            userNoticeCount = (int) queueProperties.get("QUEUE_MESSAGE_COUNT");
        }

        //封装返回的数据
        HashMap countMap = new HashMap();
        countMap.put("sysNoticeCount", noticeCount);
        countMap.put("userNoticeCount", userNoticeCount);
        Result result = new Result(true, StatusCode.OK, "查询成功", countMap);

        //把数据发送给用户
        channel.writeAndFlush(new TextWebSocketFrame(mapper.writeValueAsString(result)));


        //把消息从队列中清空,否则mq的消息监听器会在消费一次
        if (noticeCount>0){
            rabbitAdmin.purgeQueue(queueName,true);
        }

        //把消息从队列中清空,否则mq的消息监听器会在消费一次
        if (userNoticeCount>0){
            rabbitAdmin.purgeQueue(userQueueName,true);
        }
        //为用户的消息通知队列注册监听器,便于用户在线的时候
        //一旦有消息可以主动推送给用户,不需要用户请求服务器获取数据
        sysNoticeContainer.addQueueNames(queueName);
        userNoticeContainer.addQueueNames(userQueueName);
    }
}
